
/**
 * \file qdx/client/protocol.hpp
 *
 * \brief QDX Client Connection Protocol Type
 *
 */

#ifndef __QDXC_PROTOCOL_HPP__
#define __QDXC_PROTOCOL_HPP__

#include	<string>
#include	<map>
#include	<vector>

#include	"qdxc/message.hpp"
#include	"qdxc/connection.hpp"

#include	"zsocket/socket.hpp"

#define QDX_TIMEOUT     5

namespace QDX
{
    namespace   Client
    {

        /**
         * \class Connection connection.hpp
         *
         * \brief QDX Client Connection Interface
         *
         */
        class Protocol	:	public	Connection {

            public:

                /**
                 * \brief join a public group
                 *
                 * \param group [in] public group name
                 *
                 * \exception on failure
                 */
                virtual void join(const char* group = "QDXGroup");

                /**
                 * \brief leave a public group
                 *
                 * \param group [in] public group name
                 *
                 * \exception on failure
                 */
                virtual void leave(const char* group = "QDXGroup");

                /**
                 * \brief leave a public group
                 *
                 * \param group [in] public group name
                 * \param joiners [out] list of joiners 
                 *
                 * \return >=0 on success (NO. of joiners returned)
                 * \exception on failure
                 */
                virtual int query(const char* group, std::vector<std::string>& joiners );

                /**
                 * \brief send out a message
                 *
                 * \param message [in] a message to be sent out
                 * \param timeout [in] time out ( in seconds ), (no timeout by default)
                 *
                 * \exception on failure
                 */
                virtual void send(Message& message, int timeout = -1);

                /**
                 * \brief receive in a message
                 *
                 * \param message [out] a message to received 
                 * \param timeout [in] time out ( in seconds ), (no timeout by default)
                 *
                 * \exception on failure
                 */
                virtual void recv(Message& message, int timeout = -1);

                /**
                 * \brief connect to QDX NET
                 *
                 * \param hostname [in] hostname ( or IP address ) to be connected to
                 * \param port [in] port to be connected to
                 * \param myname [in] my private name
                 *
                 * \exception on failure
                 */
                virtual void connect(const char* hostname = NULL, unsigned short port = 0, const char* myname = NULL);

                /**
                 * \brief disconnect from QDX NET
                 *
                 * \exception on failure
                 */
                virtual void disconnect( void );

                /**
                 * \brief error message 
                 *
                 * \param errno [in] errno to be parsed
                 *
                 * \return error message 
                 */
                virtual	std::string	strerror ( int errno ) const;

                Protocol ();
                virtual ~Protocol ();

            protected	:
                int		helloDaemon ( void );
                int		byeDaemon ( void );

                void	debug ( const char* pszFormat, ... );
                void	trace ( const char* pszFunc, const char* pszFormat, ... );

            private	:
                void*	getpPacket ( void ) const;
                void*	getpWholePacket ( void ) const;
                void	setPacketSize ( size_t iPacketSize );
                size_t	getPacketSize ( void ) const;
                size_t	getMaxPacketSize ( void ) const;
                void*	getpPacketData ( void ) const;

                size_t	getMessageSerial ( void );

                int		parseHelloResponseOK ( std::string& strBody );
                int		parseProtocolBody ( std::string& strBody, std::map<std::string, std::string>& fields );
                int		parseQueryResponseOK ( std::string& strGroupToQuery, std::string& strBody, std::vector<std::string>& joiners );

            private	:
                zsocket::Socket     m_daemonSocket;
                zsocket::Address*   m_pDaemonAddress;
                std::string		m_strPrivateName;
                std::string		m_strPrivateGroupName;
                std::string		m_strDaemon;

                size_t			m_iMessageSerial;

                bool	m_bReady;	

                void*	m_pvPacket;
                size_t*	m_piPacketSize;
                size_t	m_iMaxPacketSize;

                unsigned int	m_iDaemonID;
                unsigned int	m_iClientID;

                FILE*	m_fileDebug;
                FILE*	m_fileTrace;
        };
    }
}

#endif // __QDX_CLIENT_PROTOCOL_HPP__

